{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 记忆模块(Memory)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 记忆组件存储的两种方式\n",
    "- 将聊天记录全部放入提示器模板，但问题是：部分LLM平台存在`Max Tokens`限制，这种方法要求如何截取、压缩聊天记录，以适应API要求。\n",
    "- 先压缩聊天记录，然后放入提示词模板中。利用LLM的总结和提取能力压缩聊天记录，或者从数据库中提取相关的聊天记录、实体知识等。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 记忆组件、链组件和Agent智能体组件的关系"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 记忆组件可以作为链组件的一部分，是一个内部组件，用于保存状态和历史信息。以便链组件在处理输入和生成输出时使用。\n",
    "- 将记忆组件放入智能体重，这使得智能体不仅能够处理和响应请求，而且还能够记住交流内容。\n",
    "- 智能体是一个更高级别的组件，它可能包含一个或多个链组件，以及与组件交互的记忆组件。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 记忆初体验\n",
    "from langchain.memory import ConversationTokenBufferMemory\n",
    "from langchain.llms import OpenAI\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.llms.openai.OpenAI` was deprecated in langchain-community 0.0.10 and will be removed in 0.2.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import OpenAI`.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# 初始化LLM\n",
    "llm = OpenAI(openai_api_key = os.environ['OPENAI_API_KEY'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始话记忆体\n",
    "memory = ConversationTokenBufferMemory(\n",
    "    llm = llm,\n",
    "    max_token_limit = 1000,\n",
    "    memory_key = \"session_chat\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 调用save_context()来保存上下文\n",
    "memory.save_context(\n",
    "    {\"input\":\"你好！我是李特丽，这是人类的第一个消息\"}, # 传入的应是一个有效的字典\n",
    "    {\"output\":\"你好！我是AI助理的第一个消息\"}\n",
    ")\n",
    "memory.save_context(\n",
    "    {\"input\":\"今天心情怎么样\"},\n",
    "    {\"output\":\"我很开心认识你\"}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'session_chat': 'Human: 你好！我是李特丽，这是人类的第一个消息\\nAI: 你好！我是AI助理的第一个消息\\nHuman: 今天心情怎么样\\nAI: 我很开心认识你'}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 加载记忆变量\n",
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 处理大量的聊天记录，或者需要在多个会话中共享聊天记录，则应该使用基于数据库集成的记忆组件类：如`SQLChatMessageHistory`、`MongoDBChatMessageHistory`。\n",
    "- 如果你主要处理实体信息，那么你需要选择`ConversationEntityMemory`或`ConversationKGMemory`这样的记忆组件。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 记忆增强检索能力的实践"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 获取外部数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 首先加载文档\n",
    "import requests\n",
    "import bs4\n",
    "from langchain_core.documents.base import Document\n",
    "\n",
    "html = \"https://www.runoob.com/python/python-tutorial.html\"\n",
    "\n",
    "html = requests.get(html).text\n",
    "\n",
    "soup = bs4.BeautifulSoup(html)\n",
    "\n",
    "text = soup.get_text()\n",
    "\n",
    "ptagList = soup.find(\"div\", class_=\"article-body\").find_all(\"p\")\n",
    "\n",
    "cleaned = \"\"\n",
    "\n",
    "for ptag in ptagList:\n",
    "    cleaned += ptag.get_text()\n",
    "\n",
    "cleaned = cleaned.replace(\"\\n\",\"\").replace(\"\\r\",\"\")\n",
    "\n",
    "# 创建文档\n",
    "\n",
    "doc = Document(\n",
    "    page_content=cleaned,\n",
    "    language = \"No language found.\"\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.embeddings.openai.OpenAIEmbeddings` was deprecated in langchain-community 0.0.9 and will be removed in 0.2.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import OpenAIEmbeddings`.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# 导入OpenAI嵌入\n",
    "from langchain.embeddings import OpenAIEmbeddings\n",
    "\n",
    "embedding = OpenAIEmbeddings(openai_api_key = os.environ['OPENAI_API_KEY'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入递归字符串分割器\n",
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "text_spliter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size = 500,\n",
    "    chunk_overlap = 0\n",
    ")\n",
    "splits = text_spliter.split_documents([doc])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建FAISS向量数据库\n",
    "from langchain.vectorstores import FAISS\n",
    "vectordb = FAISS.from_documents(documents = splits,embedding = embedding)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 加入记忆组件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 加载对话缓存记忆\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "\n",
    "memory = ConversationBufferMemory(memory_key = \"chat_history\",return_messages=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.chat_memory.add_user_message(\"我是李特丽\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'chat_history': [HumanMessage(content='我是李特丽')]}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用memory.load_memory_variables({})\n",
    "\n",
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.chat_models.openai.ChatOpenAI` was deprecated in langchain-community 0.0.10 and will be removed in 0.2.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import ChatOpenAI`.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# 初始化LLM\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.chains.question_answering import load_qa_chain\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "    openai_api_key = os.environ['OPENAI_API_KEY'],\n",
    "    model = \"gpt-3.5-turbo-0613\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"Python由谁发明？\"\n",
    "docs = vectordb.similarity_search(query)\n",
    "len(docs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "提示词内容分为四个部分：\n",
    "- 一是对模型的指导词：“请你回答问题的时候，依据文档内容和链条记录回答，如果在其中找不到相关信息或者答案，请回答不知道”。\n",
    "- 二是使用问题检索到的相关文档内容：“文档内容是：{context}”\n",
    "- 三是记忆组件输出的内容：“聊天记录是：{chat_history}”\n",
    "- 四是用户的输入：“Human: {human_input}”"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "template = \"\"\"你是说中文的chatbot\n",
    "\n",
    "请你回答问题的时候，依据文档内容和链条记录回答，如果在其中找不到相关信息或者答案，请回答不知道。\n",
    "\n",
    "文档内容是：{context}\n",
    "\n",
    "聊天记录是：{chat_history}\n",
    "Human: {human_input}\n",
    "Chatbot:\"\"\"\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    input_variables = [\"caht_history\",\"human_input\",\"context\"],\n",
    "    template = template\n",
    ")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建记忆体\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key = \"chat_history\", # 设置需要存储的键\n",
    "    input_key = \"human_input\", # 设置来自用户输入的键\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化QA链\n",
    "chain = load_qa_chain(\n",
    "    llm = llm,\n",
    "    chain_type = \"stuff\", # 设置链为stuff链 \n",
    "    memory = memory,\n",
    "    prompt = prompt,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `__call__` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n",
      "  warn_deprecated(\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'output_text': 'Python由Guido van Rossum于1989年底发明。'}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 定义query输入\n",
    "query = \"Python由谁发明？\"\n",
    "# 在向量数据库中找到近似\n",
    "docs = vectordb.similarity_search(query)\n",
    "chain({\"input_documents\":docs,\"human_input\":query},return_only_outputs=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'output_text': 'Python共经历了两个版本迭代，分别是Python 2和Python 3。'}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 尝试一些其他的问题\n",
    "query = \"Python共经历了几个版本迭代？\"\n",
    "docs = vectordb.similarity_search(query)\n",
    "chain({\"input_documents\":docs,\"human_input\":query},return_only_outputs=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'output_text': 'Python由Guido van Rossum于1989年底发明。'}"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 重试刚才的问题\n",
    "query = \"Python由谁发明？\"\n",
    "docs = vectordb.similarity_search(query)\n",
    "chain({\"input_documents\":docs,\"human_input\":query},return_only_outputs=True) # 说明记忆体已经记住了之前的问题"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Human: Python由谁发明？\\nAI: Python由Guido van Rossum于1989年底发明。\\nHuman: Python共经历了几个版本迭代？\\nAI: Python共经历了两个版本迭代，分别是Python 2和Python 3。\\nHuman: Python由谁发明？\\nAI: Python由Guido van Rossum于1989年底发明。'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用chain.memory.buffer打印记忆体存储的过往数据\n",
    "chain.memory.buffer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 记忆增强在智能体上的实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入智能体应用的工具：零样本智能体、工具类和智能体执行器\n",
    "from langchain.agents import ZeroShotAgent,AgentExecutor,Tool\n",
    "# 导入记忆体\n",
    "from langchain.memory import ConversationBufferMemory\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化LLM\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "    openai_api_key = os.environ['OPENAI_API_KEY'],\n",
    "    temperature = 0,\n",
    "    model = \"gpt-3.5-turbo-0613\"    \n",
    ")\n",
    "\n",
    "from langchain.chains import LLMChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `initialize_agent` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use Use new agent constructor methods like create_react_agent, create_json_agent, create_structured_chat_agent, etc. instead.\n",
      "  warn_deprecated(\n",
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `run` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n",
      "  warn_deprecated(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mI don't know the answer to this question off the top of my head, so I should use the search tool to find the information.\n",
      "Action: Search\n",
      "Action Input: \"OPENAI CEO\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3mSam Altman\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI now know the final answer\n",
      "Final Answer: OPENAI的CEO是Sam Altman。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'OPENAI的CEO是Sam Altman。'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 加载智能体初始化必须的函数\n",
    "from langchain.agents import initialize_agent,load_tools # 初始化智能体和加载智能体\n",
    "from langchain.agents import AgentType # 导入智能体类型\n",
    "\n",
    "# 加载智能体工具\n",
    "tools = load_tools(['serpapi','llm-math'],llm=llm)\n",
    "\n",
    "# 初始化智能体\n",
    "agent = initialize_agent(\n",
    "    tools,\n",
    "    llm,\n",
    "    agent = AgentType.ZERO_SHOT_REACT_DESCRIPTION, # 需要注意！这里的LLM类型是非Chat模型，所以引入的智能体类型必须shi\n",
    "    verbose = True\n",
    ")\n",
    "\n",
    "agent.run(\"请告诉我OPENAI的CEO是谁？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain.agents.mrkl.base.ZeroShotAgent` was deprecated in langchain 0.1.0 and will be removed in 0.2.0. Use create_react_agent instead.\n",
      "  warn_deprecated(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[32;1m\u001b[1;3mThought: 我需要搜索一下沈阳的人口数据\n",
      "Action: Search\n",
      "Action Input: \"沈阳 人口\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m8.294 million (2017)\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m我现在知道了沈阳的人口是829.4万（2017年）\n",
      "Final Answer: 沈阳的人口是829.4万（2017年）\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'沈阳的人口是829.4万（2017年）'"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建智能体\n",
    "prefix = \"\"\"你是一个说中文的chatbot,你可以使用tools帮你获得答案:\"\"\"\n",
    "suffix = \"\"\"你的中文回答是: \"\n",
    "\n",
    "聊天记录: {chat_history}\n",
    "Question: {input}\n",
    "{agent_scratchpad}\"\"\"\n",
    "\n",
    "# 创建模板\n",
    "prompt = ZeroShotAgent.create_prompt(\n",
    "    tools = tools,\n",
    "    prefix = prefix,\n",
    "    suffix = suffix,\n",
    "    input_variables = [\"chat_history\",\"input\",\"agent_scratchpad\"]\n",
    ")\n",
    "\n",
    "# 创建记忆体\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key = \"chat_history\",\n",
    ")\n",
    "\n",
    "# 创建LLM链\n",
    "llm_chain = LLMChain(llm=llm,prompt=prompt)\n",
    "\n",
    "# 实例化智能体\n",
    "agent = ZeroShotAgent(\n",
    "    llm_chain = llm_chain,\n",
    "    tools = tools,\n",
    "    verbose = True\n",
    ")\n",
    "\n",
    "# 实例化智能体执行器\n",
    "agent_chain = AgentExecutor.from_agent_and_tools(\n",
    "    agent = agent,\n",
    "    tools = tools,\n",
    "    memory = memory,\n",
    "    verbose = True\n",
    ")\n",
    "\n",
    "agent_chain.run(\"沈阳的人口是多少？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: 我需要搜索沈阳的地标建筑\n",
      "Action: Search\n",
      "Action Input: 沈阳地标建筑\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m[{'title': 'Zhao Mausoleum', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=Zhao+Mausoleum&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4gIxjSyMC6vitRSzk630c_KTE0sy8_PgDKvEkpKixGQQs3gRK19URmK-gm9iaXF-TmppLgB1MN1kTQAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIJxAB', 'description': 'Tourist attraction', 'rating': 4.4, 'reviews': 55, 'thumbnail': 'https://serpapi.com/searches/65f1495c033e94492deb4402/images/3c9ccf2e301a38836ad7906e95dd0b075dc3c1b164c2413e19a63b80c3f99fe9.jpeg'}, {'title': \"Marshal Zhang's Mansion\", 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=Marshal+Zhang%27s+Mansion&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zc0Msg2NE-O11LMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrOK-iUXFGYk5ClEZiXnp6sUKvol5xUApALfIZuFXAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIKRAB', 'description': 'Attraction', 'rating': 4.3, 'reviews': 83, 'thumbnail': 'https://serpapi.com/searches/65f1495c033e94492deb4402/images/3c9ccf2e301a38836ad7906e95dd0b075f8895a27cd73228fccee8d5520da4c2.jpeg'}, {'title': '清福陵', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=%E6%B8%85%E7%A6%8F%E9%99%B5&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4gIxTQvMDQtztBSzk630c_KTE0sy8_PgDKvEkpKixGQQs3gRK-ezHa3Pl_W_nLkVAInZhERIAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIJBAB', 'description': 'Tourist attraction', 'rating': 4.4, 'reviews': 17, 'thumbnail': 'https://serpapi.com/searches/65f1495c033e94492deb4402/images/3c9ccf2e301a38836ad7906e95dd0b07039a427a4d25fca728c26830f1003cab.jpeg'}, {'title': 'Muslim Food Street', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=Muslim+Food+Street&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zcsNzStMi3L0VLMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrEK-pcU5mbkKbvn5KQrBJUWpqSUA1K80a1IAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIPBAB', 'description': 'Chinese restaurant', 'rating': 4.3, 'reviews': 14, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipNww2Zb7SvPMsPpNy6jJaAMcGAW1e_B6WUc3d2P=w204-h114-n-k-no'}, {'title': 'Zhongshan Square', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=Zhongshan+Square&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zc0NS00TcrI0lLMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrAJRGfl56cUZiXkKwYWliUWpALm1YoVQAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIQBAB', 'description': 'Tourist attraction', 'rating': 4.0, 'reviews': 34, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipOHPqSNqgP1_3SaEcw9E4Avocjh6t-FQf3WomGm=w204-h114-n-k-no'}, {'title': 'Zhongxinmiao', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=Zhongxinmiao&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zcsSSspLCvK1VLMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrDxRGfl56RWZebmZifkAT_Xv6EwAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIOxAB', 'description': 'Place of worship', 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipP7lAE0ihbMu6fD9TfMV89poUxp8D2OsTUApiGp=w204-h114-n-k-no'}, {'title': '太清宫', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=%E5%A4%AA%E6%B8%85%E5%AE%AB&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tVP1zc0TEo2MynPKi_TUsxOttLPyU9OLMnMz4MzrBJLSooSk0HM4kWsnE-XrHq2o_XputUAUKflAEsAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIPhAB', 'description': 'Tourist attraction', 'rating': 4.1, 'reviews': 12, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipMM89KoD9WHKFWLywZNYwF78uu74qjFGqPQgjCo=w204-h114-n-k-no'}, {'title': '关东影视城', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=%E5%85%B3%E4%B8%9C%E5%BD%B1%E8%A7%86%E5%9F%8E&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zcsSS_ILS7P1lLMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrPxPWzc_2THn6d6NL5a3PZ3fBwBTVnYFTwAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIPxAB', 'description': 'Tourist attraction', 'rating': 3.9, 'reviews': 8, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipMLdglhoDA1juRTmRcN9TDLMjEyursdTBnQpEMl=w204-h114-n-k-no'}, {'title': 'Zhaoyidi Former Residence', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=Zhaoyidi+Former+Residence&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zcsSa6yMDIt0lLMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrJJRGYn5lZkpmQpu-UW5qUUKQanFmSmpecmpAOGcav1ZAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIQhAB', 'description': 'Tourist attraction', 'rating': 3.3, 'reviews': 4, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipNQszro5rhyRbQ-cSKfibeExYMRLsfG-idZ68AE=w204-h114-n-k-no'}, {'title': '护国法轮寺', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=%E6%8A%A4%E5%9B%BD%E6%B3%95%E8%BD%AE%E5%AF%BA&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tZP1zc0MjY3T8s21FLMTrbSz8lPTizJzM-DM6wSS0qKEpNBzOJFrPzPupY8nb332eapL_aue7p-FwAFysdpTwAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIPRAB', 'description': 'Tourist attraction', 'rating': 4.3, 'reviews': 3, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipMBE7WJZ3h71XPRdZptRVppCBQYkKO8_8ZZeDmY=w204-h114-n-k-no'}, {'title': '实胜寺', 'link': 'https://www.google.com/search?sca_esv=a3fcac342a8f8158&gl=us&hl=en&q=%E5%AE%9E%E8%83%9C%E5%AF%BA&stick=H4sIAAAAAAAAAONgFuLUz9U3MLTIKS9R4tFP1zfMyIgvyjW2KNZSzE620s_JT04syczPgzOsEktKihKTQcziRaycT9fNe9E85-n6XQASLyYpSgAAAA&sa=X&ved=2ahUKEwjb19Ptz_CEAxUtRTABHUlnA_0Q2coHegQIQRAB', 'description': 'Tourist attraction', 'rating': 4.3, 'reviews': 4, 'thumbnail': 'https://lh5.googleusercontent.com/p/AF1QipNochUrS_iMFdhxPrAy5bro46myURoJqHRpZFAF=w204-h114-n-k-no'}]\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m这是沈阳的一些地标建筑，包括赵陵、张氏大院、清福陵、穆斯林美食街、中山广场、中心庙、太清宫、关东影视城、赵一荻故居、护国法轮寺和实胜寺。\n",
      "Thought: 我现在知道了最终答案\n",
      "Final Answer: 沈阳的地标建筑包括赵陵、张氏大院、清福陵、穆斯林美食街、中山广场、中心庙、太清宫、关东影视城、赵一荻故居、护国法轮寺和实胜寺。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'沈阳的地标建筑包括赵陵、张氏大院、清福陵、穆斯林美食街、中山广场、中心庙、太清宫、关东影视城、赵一荻故居、护国法轮寺和实胜寺。'"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_chain.run(\"它的地标建筑是什么？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: 我需要搜索关于沈阳人口的信息\n",
      "Action: Search\n",
      "Action Input: \"沈阳人口\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m8.294 million (2017)\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m我现在知道了沈阳的人口是829.4万（2017年）\n",
      "Final Answer: 沈阳的人口是829.4万（2017年）\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'沈阳的人口是829.4万（2017年）'"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 尝试不带记忆的智能体，看看它能不能判断出“它”指代的是沈阳\n",
    "# 创建智能体\n",
    "prefix = \"\"\"你是一个说中文的chatbot,你可以使用tools帮你获得答案:\"\"\"\n",
    "suffix = \"\"\"你的中文回答是: \"\n",
    "Question: {input}\n",
    "{agent_scratchpad}\"\"\"\n",
    "\n",
    "prompt = ZeroShotAgent.create_prompt(\n",
    "    tools = tools,\n",
    "    prefix = prefix,\n",
    "    suffix = suffix,\n",
    "    input_variables = [\"input\",\"agent_scratchpad\"]\n",
    ")\n",
    "\n",
    "# 创建LLM链\n",
    "\n",
    "llm_chain = LLMChain(llm=llm,prompt=prompt)\n",
    "\n",
    "# 实例化智能体\n",
    "agent = ZeroShotAgent(\n",
    "    llm_chain = llm_chain,\n",
    "    tools = tools,\n",
    "    verbose = True\n",
    ")\n",
    "\n",
    "# 实例化智能体执行器\n",
    "agent_chain = AgentExecutor.from_agent_and_tools(\n",
    "    agent = agent,\n",
    "    tools = tools,\n",
    "    verbose = True\n",
    ")\n",
    "\n",
    "agent_chain.run(\"沈阳的人口是多少？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: 我需要搜索关于这个地方的信息\n",
      "Action: Search\n",
      "Action Input: \"地标建筑 [地方的名称]\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m['地標（英語：Landmark），指的是一類在某地區具有獨特特色的建築物、結構物或者地形、自然景觀，遊客或其他一般人可以看圖而認出自己所在之處，人造景觀種類繁多，例如 ...', '地标是指某地方具有独特地理特色的建筑物或者自然物，游客或其他一般人可以看图而认出自己身在何方，有北斗星的作用，例如摩天大楼、教堂、寺庙、雕像、灯塔、桥梁等。', '地标（英语：Landmark），指的是一类在某地区具有独特特色的建筑物、结构物或者地形、自然景观，游客或其他一般人可以看图而认出自己所在之处，人造景观种类繁多，例如 ...', '世界上最著名的26个地标建筑 · 1、吴哥窟— 柬埔寨暹粒市 · 2、悉尼歌剧院— 悉尼 · 3、埃菲尔铁塔— 巴黎 · 4、泰姬陵— 印度阿格拉 · 5、哈里法塔— 阿拉伯联合 ...', '在中国各大城市中，有上海东方明珠广播电视塔、北京故宫、广州塔、深圳地王大厦等著名标志性建筑；那么，在世界各国的地标性建筑是什么呢？ 中国——万里 ...', '标志性建筑_百度百科 也称地标性建筑，也称“地标”。 标志性建筑的基本特征就是人们可以用最简单的形态和最少的笔画来唤起对于它的记忆，一看到它就可以联想到其所在城市乃至整个国家，就像悉尼歌剧院、巴黎埃菲尔铁塔、北京天安门、比萨斜塔、东京铁塔、纽约自由女神像等世界上著名的标志性建筑一样。 标志性建筑是一个城市的名片和象征。', '小编总结了各省省会城市的地标建筑，一起来看一下吧...... 1、北京：天安门. 盘点: 中国34个省会地标建筑. 天安门原为明清两代皇城的正门，建于明永乐 ...', '世界各国著名的城市地标性建筑. 全球 ... 布拉格这个名称来自德语，当地称它为布拉哈，意 ... 几乎每个国家每个地方都有自己的地标，每个地标 ...', '台北101大楼（Taipei 101 building），前名台北国际金融中心（Taipei Financial Center），又名台北101、台北金融大楼，位于中国台湾省台北市信义区，坐落 ...']\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m这些搜索结果提到了地标建筑的定义和一些世界上著名的地标建筑。我需要进一步搜索关于特定地方的地标建筑信息。\n",
      "Action: Search\n",
      "Action Input: \"地标建筑 北京\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m{'type': 'organic_result', 'title': '北京市10 大地标 - Tripadvisor', 'source': 'Tripadvisor'}\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m这个搜索结果提到了北京市的十大地标。我可以使用这个信息来回答问题。\n",
      "Final Answer: 北京市的十大地标是：天安门广场、故宫、颐和园、长城、圆明园、天坛、北海公园、恭王府、什刹海、鸟巢。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    agent_chain.run(\"它的地标建筑是什么？\")\n",
    "except Exception:\n",
    "    print(\"模型抵达Token输出上限，无法继续执行。\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 总结记忆组件的类型与区别\n",
    "- 会话总结记忆组件(ConversationSummaryMemory)：不会逐字逐句地存储对话，而对对话内容进行摘要，并将这些摘要存储起来。这种摘要通常是整个对话的摘要，因此每次需要省的新的摘要时，都需要对大语言模型进行多次调用，以获取响应。\n",
    "- 会话缓冲区总结记忆组件(ConversationBufferSummaryMemory)：它会保存最近的交互记录，并将就得交互记录编译成摘要，同时保留二者。但与会话总结记忆组件不同的是，会话缓冲区总结记忆组件是使用标记数量而非交互次数量来决定何时清楚交互记录的。这个记忆组件设定缓冲区的标记数量限制max_token_limit，超过此限制的对话将被清除。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 两种记忆体共有的代码\n",
    "from langchain import OpenAI\n",
    "\n",
    "llm = OpenAI(\n",
    "    temperature = 0,\n",
    "    max_tokens = 256\n",
    ")\n",
    "from langchain.chains import ConversationChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 会话总结记忆组件的代码\n",
    "\n",
    "from langchain.chains.conversation.memory import ConversationSummaryMemory\n",
    "\n",
    "memory = ConversationSummaryMemory(llm = llm)\n",
    "\n",
    "conversation = ConversationChain(\n",
    "    llm = llm,\n",
    "    memory = memory,\n",
    "    verbose = True,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Human: 你好，我叫大霖，请你以简体中文回答\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？'"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 依次执行以下代码：\n",
    "conversation.predict(input = \"你好，我叫大霖，请你以简体中文回答\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "The human introduces themselves as Da Lin and asks the AI to respond in simplified Chinese. The AI introduces itself as an artificial intelligence assistant and offers to answer any questions in simplified Chinese. The human is asked if they need any assistance.\n",
      "Human: 今天的心情怎么样？\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 我是一个人工智能助手，没有情绪，所以我的心情总是很平静。您需要我为您做些什么吗？'"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"今天的心情怎么样？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Da Lin introduces themselves and asks the AI to respond in simplified Chinese. The AI introduces itself as an artificial intelligence assistant and offers to answer any questions in simplified Chinese. Da Lin asks how the AI is feeling today and the AI responds that it does not have emotions, so its mood is always calm. The AI then asks if Da Lin needs any assistance.\n",
      "Human: 我想找客户服务中心\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 您好，我是一个人工智能助手。您需要帮助吗？我可以用简体中文回答您的问题。'"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我想找客户服务中心\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Da Lin introduces themselves and asks the AI to respond in simplified Chinese. The AI introduces itself as an artificial intelligence assistant and offers to answer any questions in simplified Chinese. Da Lin asks how the AI is feeling today and the AI responds that it does not have emotions, so its mood is always calm. The AI then asks if Da Lin needs any assistance. Da Lin asks for help finding the customer service center and the AI offers to assist in simplified Chinese.\n",
      "Human: 我的笔记本电脑坏了\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 很抱歉听到这个消息。我可以帮你找到客服中心，他们可以帮助你修理笔记本电脑。你需要我帮你联系客服中心吗？'"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的笔记本电脑坏了\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 会话缓冲区总结以及\n",
    "from langchain.chains.conversation.memory import ConversationSummaryBufferMemory\n",
    "\n",
    "memory = ConversationSummaryBufferMemory(\n",
    "    llm = OpenAI(),\n",
    "    max_tokens_limit = 40\n",
    ")\n",
    "\n",
    "conversation = ConversationChain(\n",
    "    llm = OpenAI(),\n",
    "    memory = memory,\n",
    "    verbose = True,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Human: 你好，我是大霖\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 你好大霖！很高兴认识你。我是一个人工智能助手，叫做小慧。我可以回答你的任何问题，或者帮助你做一些事情。你有什么需要我的帮助吗？'"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 请依次运行以下代码\n",
    "conversation.predict(input = \"你好，我是大霖\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖\n",
      "AI:  你好大霖！很高兴认识你。我是一个人工智能助手，叫做小慧。我可以回答你的任何问题，或者帮助你做一些事情。你有什么需要我的帮助吗？\n",
      "Human: 今天的心情怎么样？\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 我是一个人工智能，没有情绪。但是我可以通过分析数据来给出今天的天气情况。今天的天气预报显示，全天有阴天，最高气温为26℃，最低气温为18℃。如果您出门的话，最好带上一件外套。'"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"今天的心情怎么样？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖\n",
      "AI:  你好大霖！很高兴认识你。我是一个人工智能助手，叫做小慧。我可以回答你的任何问题，或者帮助你做一些事情。你有什么需要我的帮助吗？\n",
      "Human: 今天的心情怎么样？\n",
      "AI:  我是一个人工智能，没有情绪。但是我可以通过分析数据来给出今天的天气情况。今天的天气预报显示，全天有阴天，最高气温为26℃，最低气温为18℃。如果您出门的话，最好带上一件外套。\n",
      "Human: 我想找客户服务中心\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 好的，您可以通过拨打客户服务热线电话或者在网站上寻找客户服务中心的地址。我可以帮您查询客户服务热线电话，但是我不知道您需要联系哪家公司的客户服务中心。可以告诉我您要联系的公司名称吗？'"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我想找客户服务中心\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖\n",
      "AI:  你好大霖！很高兴认识你。我是一个人工智能助手，叫做小慧。我可以回答你的任何问题，或者帮助你做一些事情。你有什么需要我的帮助吗？\n",
      "Human: 今天的心情怎么样？\n",
      "AI:  我是一个人工智能，没有情绪。但是我可以通过分析数据来给出今天的天气情况。今天的天气预报显示，全天有阴天，最高气温为26℃，最低气温为18℃。如果您出门的话，最好带上一件外套。\n",
      "Human: 我想找客户服务中心\n",
      "AI:  好的，您可以通过拨打客户服务热线电话或者在网站上寻找客户服务中心的地址。我可以帮您查询客户服务热线电话，但是我不知道您需要联系哪家公司的客户服务中心。可以告诉我您要联系的公司名称吗？\n",
      "Human: 我的笔记本电脑坏了\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 那么您需要联系的可能是电脑品牌的客户服务中心。您知道您的电脑是哪个品牌的吗？我可以帮您查询该品牌的客户服务热线电话。'"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的笔记本电脑坏了\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 会话记忆组件和会话窗口记忆组件的对比"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import OpenAI\n",
    "llm = OpenAI(\n",
    "    temperature=0,\n",
    "    max_tokens=256\n",
    ")\n",
    "from langchain.chains import ConversationChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 会话记忆组件\n",
    "from langchain.chains.conversation.memory import ConversationBufferMemory\n",
    "\n",
    "memory = ConversationBufferMemory()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 重新初始化对话链\n",
    "conversation = ConversationChain(\n",
    "    llm = llm,\n",
    "    memory = memory,\n",
    "    verbose = True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？'"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"你好，我是大霖，请你以简体中文回答\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 我是一个人工智能助手，没有情绪，所以无法回答你的问题。但是，我可以告诉你今天的天气如何。根据我的数据，今天的天气是晴朗的，气温在25度左右，适合出门活动。你有什么其他的问题吗？'"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"今天心情怎么样？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个人工智能助手，没有情绪，所以无法回答你的问题。但是，我可以告诉你今天的天气如何。根据我的数据，今天的天气是晴朗的，气温在25度左右，适合出门活动。你有什么其他的问题吗？\n",
      "Human: 我想找客户服务中心\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 当然，我可以帮你找到客户服务中心的联系方式。请问你需要联系哪个公司的客户服务中心？'"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我想找客户服务中心\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个人工智能助手，没有情绪，所以无法回答你的问题。但是，我可以告诉你今天的天气如何。根据我的数据，今天的天气是晴朗的，气温在25度左右，适合出门活动。你有什么其他的问题吗？\n",
      "Human: 我想找客户服务中心\n",
      "AI:  当然，我可以帮你找到客户服务中心的联系方式。请问你需要联系哪个公司的客户服务中心？\n",
      "Human: 我的笔记本电脑坏了\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'  那你需要联系电脑品牌的客户服务中心。我可以为你搜索一下，你需要哪个品牌的客户服务中心？'"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的笔记本电脑坏了\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 会话窗口记忆组件的代码\n",
    "from langchain.chains.conversation.memory import ConversationBufferWindowMemory\n",
    "\n",
    "memory = ConversationBufferWindowMemory(k = 2)\n",
    "\n",
    "conversation = ConversationChain(\n",
    "    llm = llm,\n",
    "    memory = memory,\n",
    "    verbose = True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？'"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"你好，我是大霖，请你以简体中文回答\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 我是一个人工智能助手，没有情绪，所以无法回答你的问题。但是，我可以告诉你今天的天气如何。根据我的数据，今天的天气是晴朗的，气温在25度左右，适合出门活动。'"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"今天心情怎么样？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我是一个人工智能助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个人工智能助手，没有情绪，所以无法回答你的问题。但是，我可以告诉你今天的天气如何。根据我的数据，今天的天气是晴朗的，气温在25度左右，适合出门活动。\n",
      "Human: 我想找客户服务中心\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 当然，我可以帮你找到客户服务中心的联系方式。请问你需要联系哪个公司的客户服务中心？'"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我想找客户服务中心\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个人工智能助手，没有情绪，所以无法回答你的问题。但是，我可以告诉你今天的天气如何。根据我的数据，今天的天气是晴朗的，气温在25度左右，适合出门活动。\n",
      "Human: 我想找客户服务中心\n",
      "AI:  当然，我可以帮你找到客户服务中心的联系方式。请问你需要联系哪个公司的客户服务中心？\n",
      "Human: 我的笔记本电脑坏了\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 那你可能需要联系电脑品牌的客户服务中心。我可以为你搜索一下，你需要联系哪个品牌的客户服务中心？'"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的笔记本电脑坏了\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 知识图谱记忆组件和实体记忆组件的比较"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "知识图谱记忆组件是一种特殊类型的记忆组件，它能够根据对话内容构建出一个信息网络。每当它认识别到相关的信息时，都会接收这些信息并逐步构建出一个小型的知识图谱。与此同时，这种类型的记忆组件也会产生一种特殊的数据类型-知识图谱数据类型。\n",
    "\n",
    "另一方面，实体记忆组件则专注于在对话中提取特定实体的信息。它使用大语言模型提取实体信息，并随着时间推移，通过同样的方式基类关于这个实体的体积。因此，实体记忆组件给出的结果通常是关于特定事物的关键信息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入LLM、链和模板\n",
    "from langchain import OpenAI\n",
    "\n",
    "llm = OpenAI(temperature=0,max_tokens=256)\n",
    "\n",
    "from langchain.chains import ConversationChain\n",
    "from langchain.prompts.prompt import PromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 针对知识图谱记忆体的代码\n",
    "from langchain.chains.conversation.memory import ConversationKGMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建模板\n",
    "template = \"\"\"\n",
    "The following is a friendly conversation between a human and an AI.The AI is talkative and provides lots of specific details from its context.\n",
    "If the AI does not know the answer to a question,it truthfully says it does not know.The AI ONLY uses information contained in the \"Relevant Information\"\n",
    "section and does not hallucinate.\n",
    "\n",
    "Relevant Information:\n",
    "\n",
    "{history}\n",
    "\n",
    "Conversation:\n",
    "Human:{input}\n",
    "AI:\"\"\"\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    input_variables = [\"history\",\"input\"],\n",
    "    template = template\n",
    ")\n",
    "\n",
    "conversation = ConversationChain(\n",
    "    llm = llm,\n",
    "    memory = ConversationKGMemory(llm = llm),\n",
    "    prompt = prompt,\n",
    "    verbose = True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "The following is a friendly conversation between a human and an AI.The AI is talkative and provides lots of specific details from its context.\n",
      "If the AI does not know the answer to a question,it truthfully says it does not know.The AI ONLY uses information contained in the \"Relevant Information\"\n",
      "section and does not hallucinate.\n",
      "\n",
      "Relevant Information:\n",
      "\n",
      "\n",
      "\n",
      "Conversation:\n",
      "Human:你好，我是大霖，请你以简体中文回答\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 你好，大霖。我是一名AI助手，可以用简体中文回答你的问题。请问你有什么需要帮助的吗？'"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"你好，我是大霖，请你以简体中文回答\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "The following is a friendly conversation between a human and an AI.The AI is talkative and provides lots of specific details from its context.\n",
      "If the AI does not know the answer to a question,it truthfully says it does not know.The AI ONLY uses information contained in the \"Relevant Information\"\n",
      "section and does not hallucinate.\n",
      "\n",
      "Relevant Information:\n",
      "\n",
      "\n",
      "\n",
      "Conversation:\n",
      "Human:今天心情怎么样？\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 我是一个AI，没有情绪，所以我的心情一直都很平静。不过，根据我的数据分析，今天的天气是晴朗的，气温为25摄氏度，空气质量良好，适合户外活动。您有什么计划吗？'"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"今天心情怎么样？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "The following is a friendly conversation between a human and an AI.The AI is talkative and provides lots of specific details from its context.\n",
      "If the AI does not know the answer to a question,it truthfully says it does not know.The AI ONLY uses information contained in the \"Relevant Information\"\n",
      "section and does not hallucinate.\n",
      "\n",
      "Relevant Information:\n",
      "\n",
      "\n",
      "\n",
      "Conversation:\n",
      "Human:我想找客户服务中心\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 您好，欢迎来到客户服务中心。我是这里的AI助手，很高兴为您服务。请问您需要什么帮助？'"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我想找客户服务中心\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "The following is a friendly conversation between a human and an AI.The AI is talkative and provides lots of specific details from its context.\n",
      "If the AI does not know the answer to a question,it truthfully says it does not know.The AI ONLY uses information contained in the \"Relevant Information\"\n",
      "section and does not hallucinate.\n",
      "\n",
      "Relevant Information:\n",
      "\n",
      "\n",
      "\n",
      "Conversation:\n",
      "Human:我的笔记本电脑坏了，出现了Invalid Partion table!的字样，请用中文告诉我该怎么办\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 您好，根据我的资料，Invalid Partition Table是指硬盘分区表出现错误，导致无法正常启动电脑。您可以尝试使用Windows安装盘来修复分区表，或者使用命令行工具来重建分区表。如果这些方法都无法解决问题，可能需要更换硬盘。'"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的笔记本电脑坏了，出现了Invalid Partion table!的字样，请用中文告诉我该怎么办\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "The following is a friendly conversation between a human and an AI.The AI is talkative and provides lots of specific details from its context.\n",
      "If the AI does not know the answer to a question,it truthfully says it does not know.The AI ONLY uses information contained in the \"Relevant Information\"\n",
      "section and does not hallucinate.\n",
      "\n",
      "Relevant Information:\n",
      "\n",
      "\n",
      "\n",
      "Conversation:\n",
      "Human:我的保修卡编号是A512343\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'你好，我的名字是AI助手，很高兴认识你。根据我的记录，你的保修卡编号是A512343。这是一张有效的保修卡，它包含了你购买的产品的详细信息，如品牌、型号、购买日期等。你可以在需要维修或更换产品时使用它。另外，根据保修条款，你的产品在购买后的一年内享受免费维修服务。如果你有任何问题，我可以帮你查询更多信息。'"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的保修卡编号是A512343\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('客户服务中心', '欢迎来到', '是'), ('客户服务中心', 'AI助手', '是'), ('客户服务中心', '帮助', '需要'), ('笔记本电脑', 'Invalid Partition table', '坏了'), ('Invalid Partition table', '字样', '是'), ('Invalid Partition table', '硬盘分区表出现错误', '是指'), ('我的笔记本电脑', '出现了Invalid Partition table', '坏了'), ('硬盘分区表', '无法正常启动电脑', '导致'), ('您', '使用Windows安装盘来修复分区表', '可以尝试'), ('您', '使用命令行工具来重建分区表', '可以尝试'), ('如果这些方法', '可能需要更换硬盘', '都无法解决问题'), ('保修卡', '有效的', '是'), ('保修卡', '品牌', '包含'), ('保修卡', '型号', '包含'), ('保修卡', '购买日期', '包含'), ('保修卡', '需要维修或更换产品时使用', '可以在'), ('保修卡', '保修条款', '根据'), ('保修卡', '享受免费维修服务', '在购买后的一年内')]\n"
     ]
    }
   ],
   "source": [
    "# 查看知识图谱\n",
    "print(conversation.memory.kg.get_triples())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 实体记忆组件的代码\n",
    "from langchain.chains.conversation.memory import ConversationEntityMemory\n",
    "from langchain.chains.conversation.prompt import ENTITY_MEMORY_CONVERSATION_TEMPLATE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建会话链\n",
    "conversation = ConversationChain(\n",
    "    llm = llm,\n",
    "    verbose = True,\n",
    "    prompt = ENTITY_MEMORY_CONVERSATION_TEMPLATE,\n",
    "    memory = ConversationEntityMemory(llm = llm)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mYou are an assistant to a human, powered by a large language model trained by OpenAI.\n",
      "\n",
      "You are designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, you are able to generate human-like text based on the input you receive, allowing you to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n",
      "\n",
      "You are constantly learning and improving, and your capabilities are constantly evolving. You are able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. You have access to some personalized information provided by the human in the Context section below. Additionally, you are able to generate your own text based on the input you receive, allowing you to engage in discussions and provide explanations and descriptions on a wide range of topics.\n",
      "\n",
      "Overall, you are a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether the human needs help with a specific question or just wants to have a conversation about a particular topic, you are here to assist.\n",
      "\n",
      "Context:\n",
      "{'大霖': '', '简体中文': ''}\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Last line:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "You:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 你好，大霖。我会尽力以简体中文回答你的问题。有什么可以帮到你的吗？'"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"你好，我是大霖，请你以简体中文回答\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mYou are an assistant to a human, powered by a large language model trained by OpenAI.\n",
      "\n",
      "You are designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, you are able to generate human-like text based on the input you receive, allowing you to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n",
      "\n",
      "You are constantly learning and improving, and your capabilities are constantly evolving. You are able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. You have access to some personalized information provided by the human in the Context section below. Additionally, you are able to generate your own text based on the input you receive, allowing you to engage in discussions and provide explanations and descriptions on a wide range of topics.\n",
      "\n",
      "Overall, you are a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether the human needs help with a specific question or just wants to have a conversation about a particular topic, you are here to assist.\n",
      "\n",
      "Context:\n",
      "{}\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我会尽力以简体中文回答你的问题。有什么可以帮到你的吗？\n",
      "Last line:\n",
      "Human: 今天心情怎么样？\n",
      "You:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 我是一个语言模型，没有情绪。但是我可以帮你回答关于今天的天气、新闻、或者其他话题。你想要了解什么？'"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"今天心情怎么样？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mYou are an assistant to a human, powered by a large language model trained by OpenAI.\n",
      "\n",
      "You are designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, you are able to generate human-like text based on the input you receive, allowing you to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n",
      "\n",
      "You are constantly learning and improving, and your capabilities are constantly evolving. You are able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. You have access to some personalized information provided by the human in the Context section below. Additionally, you are able to generate your own text based on the input you receive, allowing you to engage in discussions and provide explanations and descriptions on a wide range of topics.\n",
      "\n",
      "Overall, you are a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether the human needs help with a specific question or just wants to have a conversation about a particular topic, you are here to assist.\n",
      "\n",
      "Context:\n",
      "{}\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我会尽力以简体中文回答你的问题。有什么可以帮到你的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个语言模型，没有情绪。但是我可以帮你回答关于今天的天气、新闻、或者其他话题。你想要了解什么？\n",
      "Last line:\n",
      "Human: 我想找客户服务中心\n",
      "You:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 您可以尝试联系客户服务中心的电话号码，或者通过他们的网站寻求帮助。您也可以尝试发送电子邮件或者通过社交媒体平台与客户服务中心联系。'"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我想找客户服务中心\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mYou are an assistant to a human, powered by a large language model trained by OpenAI.\n",
      "\n",
      "You are designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, you are able to generate human-like text based on the input you receive, allowing you to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n",
      "\n",
      "You are constantly learning and improving, and your capabilities are constantly evolving. You are able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. You have access to some personalized information provided by the human in the Context section below. Additionally, you are able to generate your own text based on the input you receive, allowing you to engage in discussions and provide explanations and descriptions on a wide range of topics.\n",
      "\n",
      "Overall, you are a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether the human needs help with a specific question or just wants to have a conversation about a particular topic, you are here to assist.\n",
      "\n",
      "Context:\n",
      "{'Invalid Partion table': ''}\n",
      "\n",
      "Current conversation:\n",
      "Human: 你好，我是大霖，请你以简体中文回答\n",
      "AI:  你好，大霖。我会尽力以简体中文回答你的问题。有什么可以帮到你的吗？\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个语言模型，没有情绪。但是我可以帮你回答关于今天的天气、新闻、或者其他话题。你想要了解什么？\n",
      "Human: 我想找客户服务中心\n",
      "AI:  您可以尝试联系客户服务中心的电话号码，或者通过他们的网站寻求帮助。您也可以尝试发送电子邮件或者通过社交媒体平台与客户服务中心联系。\n",
      "Last line:\n",
      "Human: 我的笔记本电脑坏了，出现了Invalid Partion table!的字样，请用中文告诉我该怎么办\n",
      "You:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 首先，您可以尝试重启电脑，看看是否能够解决问题。如果问题仍然存在，您可以尝试使用系统恢复功能来修复分区表。如果这些方法都无效，您可能需要联系电脑维修专家来解决这个问题。'"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的笔记本电脑坏了，出现了Invalid Partion table!的字样，请用中文告诉我该怎么办\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mYou are an assistant to a human, powered by a large language model trained by OpenAI.\n",
      "\n",
      "You are designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, you are able to generate human-like text based on the input you receive, allowing you to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n",
      "\n",
      "You are constantly learning and improving, and your capabilities are constantly evolving. You are able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. You have access to some personalized information provided by the human in the Context section below. Additionally, you are able to generate your own text based on the input you receive, allowing you to engage in discussions and provide explanations and descriptions on a wide range of topics.\n",
      "\n",
      "Overall, you are a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether the human needs help with a specific question or just wants to have a conversation about a particular topic, you are here to assist.\n",
      "\n",
      "Context:\n",
      "{}\n",
      "\n",
      "Current conversation:\n",
      "Human: 今天心情怎么样？\n",
      "AI:  我是一个语言模型，没有情绪。但是我可以帮你回答关于今天的天气、新闻、或者其他话题。你想要了解什么？\n",
      "Human: 我想找客户服务中心\n",
      "AI:  您可以尝试联系客户服务中心的电话号码，或者通过他们的网站寻求帮助。您也可以尝试发送电子邮件或者通过社交媒体平台与客户服务中心联系。\n",
      "Human: 我的笔记本电脑坏了，出现了Invalid Partion table!的字样，请用中文告诉我该怎么办\n",
      "AI:  首先，您可以尝试重启电脑，看看是否能够解决问题。如果问题仍然存在，您可以尝试使用系统恢复功能来修复分区表。如果这些方法都无效，您可能需要联系电脑维修专家来解决这个问题。\n",
      "Last line:\n",
      "Human: 我的保修卡编号是A512343\n",
      "You:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "' 您可以将保修卡编号提供给客户服务中心，他们可以帮助您查询保修信息并提供相应的服务。'"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input = \"我的保修卡编号是A512343\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n"
     ]
    }
   ],
   "source": [
    "# 打印实体缓存\n",
    "print(conversation.memory.entity_cache)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
